#include<cstdint>
#include<iostream>
#include<functional>
#include<memory>
#include<vector>
#include<unistd.h>
#include<unordered_map>
//封装定时任务对象
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimeTask
{
private:
    uint64_t _id;//任务id
    uint32_t _timeout;//任务延时
    TaskFunc _task_cb;//具体任务
    ReleaseFunc _release;//删除容器里的任务信息
    bool _del;

public:
 void Del()
    {
        _del = true;
    }
    TimeTask(uint64_t id,uint32_t delay,const TaskFunc& task,bool del)
        :_id(id),_timeout(delay),_task_cb(task),_del(del)
        {}
    ~TimeTask()//析构时执行任务，并删除任务信息
    {
        //如果被取消，则不执行任务只销毁
        if(!_del)
        _task_cb();//执行任务
        _release();
    }
    void SetReleaseFunc(const ReleaseFunc& release)
    {
        _release = release;
    }
    uint32_t GetDelay(){
        return _timeout;
    }

};

class TimeWheel
{
private:
    using WeakPtr = std::weak_ptr<TimeTask>;
    using PtrTask = std::shared_ptr<TimeTask>;
    std::vector<std::vector<PtrTask>> _wheel;//时间轮子:存放智能指针
    std::unordered_map<uint64_t,WeakPtr> _timer;//管理数据结构：id与任务，存放弱指针
    int _tick;//指针
    int _capacity;
private:
    //从timer删除,维护数据
    void RemoveTimer(uint64_t id)
    {
        auto it = _timer.find(id);
        if(it != _timer.end())
        {
            _timer.erase(id);
        }
    }
   
public:
    TimeWheel():_capacity(60),_tick(0),_wheel(_capacity){}
    void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc& task,bool del){
        //构建智能指针任务对象
        PtrTask p(new TimeTask(id,delay,task,false));
        p->SetReleaseFunc(std::bind(&TimeWheel::RemoveTimer,this,id));
        //计算下标
        int pos = (_tick + delay) % _capacity;
        //存放到timer
        _timer[id] = WeakPtr(p);//map
        _wheel[pos].push_back(p);//二维数组
        //存放到时间轮里
    }
    //刷新任务
    void TimerRefresh(uint64_t id)
    {
        //找到对应的任务
        auto it = _timer.find(id);
        if(it == _timer.end())
        {
            return;
        }
        //构造智能指针，计算延时位置，插入到时间轮
        PtrTask p = it->second.lock();
        uint32_t delay = p->GetDelay();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(p);
    }
    //不执行任务，只销毁在timer里的存储
    void TimerDel(uint64_t id){
     //找到对应的任务
        auto it = _timer.find(id);
        if(it == _timer.end())
        {
            return;
        }
        PtrTask p = it->second.lock();
        if(p) p->Del();

    }
    void RunTime()
    {
        _tick = (_tick+1) % _capacity;
        _wheel[_tick].clear();
    }
};
//测试类
class Test
{
public:
    Test(){std::cout<<"构造"<<std::endl;}
    ~Test()
    {
        std::cout<<"析构"<<std::endl;
    }
};
void DelTask(Test* t)
{
    delete t;
}
int main()
{
    TimeWheel tw;
    Test* t = new Test();
    //添加任务
    //封装了一个任务对象，任务对象析构时，执行的回调函数是析构Test类
    tw.TimerAdd(888,5,std::bind(DelTask,t),false);
    //不断刷新任务
    for(int i = 0;i < 3;i++)
    {
        sleep(1);
        tw.RunTime();//先让tick走起来
        tw.TimerRefresh(888);
        std::cout<<"刷新任务，延时1s"<<std::endl;
    }
    //执行任务
    while(1)
    {
        sleep(1);
        std::cout<<"++++++++++++++++++"<<std::endl;
        tw.RunTime();//tick指针不停地走，直到销毁所有智能指针，执行析构函数
    }
    
    
    return 0;
}